package com.lenovo.nova.util.os;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.ActivityManager.MemoryInfo;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Process;
import android.os.RemoteException;

import com.lenovo.nova.service.IRemoteExecute;
import com.lenovo.nova.util.StringUtil;
import com.lenovo.nova.util.collection.Collections;
import com.lenovo.nova.util.exec.JavaShellUtil;
import com.lenovo.nova.util.os.storage.StorageUtil;

public class PackageActivityManagerUtil extends InternalPkgActivityManager{
	private static PackageActivityManagerUtil instance;
	private PackageManager mPkgManager;
	private ActivityManager mActManager;
	private Context mContext;

	
	public PackageActivityManagerUtil(Context context) {
		initByContext(context);
	}

	public void initByContext(Context context) {
		mContext = context;
		mPkgManager = context.getApplicationContext().getPackageManager();
		mActManager = (ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
	}

	public void release(){
		mContext = null;
		mPkgManager = null;
		mActManager = null;
	}
	
	/**
	 * 获取内存的可用率
	 * 
	 * @return
	 */
	@SuppressLint("NewApi")
	public float getMemoryFreeRate() {
		MemoryInfo memoryinfo = new android.app.ActivityManager.MemoryInfo();
		mActManager.getMemoryInfo(memoryinfo);
		
		return (float) memoryinfo.availMem / memoryinfo.totalMem;
	}

	/**
	 * 获取存取信息的可用率
	 * 
	 * @return
	 */
	public float getStorageFreeRage() {
		StorageUtil suti = new StorageUtil();
		long size = suti.getExternalStorageSize();
		long avaliableSize = suti.getExternalAvaliableStorageSize();
		return (1 - (float) avaliableSize / size);
	}

	public boolean forceStopPackage(String pkg){
		try {
			mActManager.forceStopPackage(pkg);
		} catch (Exception e) {
			return false;
		}
		
		return true;
	}
	
	/**
	 * 获取已经安装的应用
	 * 
	 * @return
	 */
	public List<PackageInfo> getInstalledPackages() {
		List<PackageInfo> list = mPkgManager.getInstalledPackages(PackageManager.GET_ACTIVITIES);
		System.out.println("size is " + list.size());
		int size = 0;
		for (PackageInfo packageInfo : list) {
			ApplicationInfo appInfo = packageInfo.applicationInfo;
			if ((appInfo.flags & ApplicationInfo.FLAG_STOPPED) == 0) {
				System.out.println(appInfo.loadLabel(mPkgManager) + "    " + appInfo.sourceDir);
				size++;
			}
		}
		System.out.println("size is " + size);
		return list;

	}


	/**
	 * 获取正在运行的应用
	 * @return
	 */
	public List<RunningAppProcessInfoWrap> getRuningAppProcesses(String filterPckage[]) {
		List<RunningAppProcessInfo> RuningPrceInfo = mActManager.getRunningAppProcesses();
		List<RunningAppProcessInfoWrap> result = new ArrayList<PackageActivityManagerUtil.RunningAppProcessInfoWrap>();
		final int numProc = RuningPrceInfo.size();
		int[] pids = new int[numProc];

		for (int i = 0; i < RuningPrceInfo.size(); i++) {
			pids[i] = RuningPrceInfo.get(i).pid;
		}

		try {
			long[] pss = ActivityManagerNative.getDefault().getProcessPss(pids);
			for (int i = 0; i < pids.length; i++) {
				RunningAppProcessInfo proc = RuningPrceInfo.get(i);
				System.out.println("progressname ===== " + proc.processName);
				Collections.showCollection(Arrays.asList(proc.pkgList), null);
				
				long mSize = pss[i] * 1024;
				boolean isAddToList = true;
				if(filterPckage != null){
					for (String fpkg : filterPckage) {
						if(proc.processName.equals(fpkg)){
							isAddToList = false;
							break;
						}
					
						if(proc.pkgList.length > 1){
							for(String ppkg : proc.pkgList){
								if(ppkg!=null && ppkg.equals(fpkg)){
									isAddToList = false;
									break;
								}
							}
						}
					}
				}
				if(isAddToList){
					result.add(new RunningAppProcessInfoWrap(proc, mSize));
				}
			}
		} catch (RemoteException e) {
			e.printStackTrace();
		}

		debug(RuningPrceInfo);

		return result;
	}

	private void debug(List<RunningAppProcessInfo> RuningPrceInfo) {
		Set<String> set = new HashSet<String>();
		for (RunningAppProcessInfo runningAppProcessInfo : RuningPrceInfo) {
			set.add(runningAppProcessInfo.processName + "\t" + getApplicatLabelName(runningAppProcessInfo.pkgList[0]));
		}
		System.out.println("set size is " + set.size());
		StringUtil.showCollection(set, null);
	}

	/**
	 * 获取应用的名称
	 * 
	 * @param pkg
	 * @return
	 */
	public String getApplicatLabelName(String pkg) {
		try {
			ApplicationInfo info = mPkgManager.getApplicationInfo(pkg, 0);
			return (String) info.loadLabel(mPkgManager);
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Deprecated
	public static PackageActivityManagerUtil getCurrentInstance(Context context) {
		if (instance == null) {
			instance = new PackageActivityManagerUtil(context);
		}
		instance.initByContext(context);
		return instance;
	}

	public ActivityManager getActivityManager() {
		return mActManager;
	}

	public class RunningAppProcessInfoWrap {

		public RunningAppProcessInfoWrap(RunningAppProcessInfo info, long size) {
			this.info = info;
			this.size = size;
			formatSize = StringUtil.formatShortSize(mContext, size);
			ensureLabel(mPkgManager);
		}
		
		public RunningAppProcessInfoWrap(String pgkName) {
			this.packageName = pgkName;
			try {
				mLabel = (String) mPkgManager.getApplicationLabel(mPkgManager.getApplicationInfo(pgkName, 0));
			} catch (NameNotFoundException e) {
				e.printStackTrace();
			}
		}
		
		public RunningAppProcessInfo info;
		/**
		 * 在用于标识正在运行的进程的时候 packageName is null
		 */
		public String packageName;
		public long size;
		public String formatSize;
		public String mLabel;
		public boolean mEnable;
		public int mBootFlag;
		
		public List<String> compones = new ArrayList<String>();
		
		void ensureLabel(PackageManager pm) {
			if (mLabel != null) {
				return;
			}
			try {
				ApplicationInfo ai = pm.getApplicationInfo(info.processName, PackageManager.GET_UNINSTALLED_PACKAGES);
				mLabel = ai.loadLabel(pm) + "";
				return;

			} catch (PackageManager.NameNotFoundException e) {
			}

			// If we couldn't get information about the overall
			// process, try to find something about the uid.
			String[] pkgs = pm.getPackagesForUid(info.uid);

			// If there is one package with this uid, that is what we want.
			if (pkgs.length == 1) {
				try {
					ApplicationInfo ai = pm.getApplicationInfo(pkgs[0], PackageManager.GET_UNINSTALLED_PACKAGES);
					mLabel = ai.loadLabel(pm).toString();
					return;
				} catch (PackageManager.NameNotFoundException e) {
				}
			}

			// If there are multiple, see if one gives us the official name
			// for this uid.
			for (String name : pkgs) {
				try {
					PackageInfo pi = pm.getPackageInfo(name, 0);
					if (pi.sharedUserLabel != 0) {
						CharSequence nm = pm.getText(name, pi.sharedUserLabel, pi.applicationInfo);
						if (nm != null) {
							mLabel = nm.toString();
							return;
						}
					}
				} catch (PackageManager.NameNotFoundException e) {
				}
			}

			// Finally... whatever, just pick the first package's name.
			try {
				ApplicationInfo ai = pm.getApplicationInfo(pkgs[0], PackageManager.GET_UNINSTALLED_PACKAGES);
				mLabel = ai.loadLabel(pm).toString();
				return;
			} catch (PackageManager.NameNotFoundException e) {
			}
		}
		
		public void add(String component) {
			compones.add(component);
		}
		public void setDispName(String string) {
			
		}

	}

	
	 /**
     * 判断应用自启动状态 默认为false 0:没有自启动能力 1:开机自启 2:后台自启 3:开机自启和后台自启
     * 
     * @param context
     * @param packageName
     * @return
     */
    public int checkAutoLaunchStatus(Context context, String packageName) {
        PackageManager pm = context.getPackageManager();
        int status = 0;
        Intent intent = new Intent();
        intent.setPackage(packageName);
        intent.setAction(BOOT_COMPLEMENT_ACTION);
        String args[] = new String[2];
        List<ResolveInfo> list = pm.queryBroadcastReceivers(intent, 512);
        if (list != null && list.size() > 0) {
            Iterator<ResolveInfo> rifInterator = list.iterator();
            while (rifInterator.hasNext()) {
                ResolveInfo rif = (ResolveInfo) rifInterator.next();
                args[0] = packageName;
                args[1] = rif.activityInfo.name;
                String component = String.format("%s/%s", args);
                ComponentName cn = ComponentName.unflattenFromString(component);
                //                if (pm.getComponentEnabledSetting(cn) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
                //                    
                //                }
                status++;
                break;
            }
        }
      
        int length = BACKGROUND_BOOT_RECEIVER.length;
        boolean isBackgroundAuto = false;
        for (int i = 0; i < length; i++) {
            intent.setPackage(packageName);
            intent.setAction(BACKGROUND_BOOT_RECEIVER[i]);
            List<ResolveInfo> rifList = pm.queryBroadcastReceivers(intent, 512);
            if (rifList != null && rifList.size() > 0) {
                Iterator<ResolveInfo> rifInterator = rifList.iterator();
                while (rifInterator.hasNext()) {
                    ResolveInfo rif = (ResolveInfo) rifInterator.next();
                    args[0] = packageName;
                    args[1] = rif.activityInfo.name;
                    String component = String.format("%s/%s", args);
                    ComponentName cn = ComponentName.unflattenFromString(component);
                    //                    if (pm.getComponentEnabledSetting(cn) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
                    //                        
                    //                    }
                    if (status == 1)
                        status = 3;
                    else {
                        status = 2;
                    }
                    isBackgroundAuto = true;
                    break;
                }
            }
            if (isBackgroundAuto) break;
        }

        return status;
    }
    
    /**
     * 判断是系统应用or3rd应用
     * 
     * @param app
     * @return
     */
    public static boolean isSystemApplications(android.content.pm.ApplicationInfo app) {
        return (app.flags & app.FLAG_SYSTEM) > 0;
    }
    
    /**
     * 获取自启动应用列表
     * @param apkList
     * @param context
     * @return
     */
    public ArrayList<RunningAppProcessInfoWrap> getAutoRunApplication(Context context,boolean rootPermission) {
    	ArrayList<RunningAppProcessInfoWrap> apkList = new ArrayList<PackageActivityManagerUtil.RunningAppProcessInfoWrap>();
        PackageManager pm = context.getPackageManager();
        List<PackageInfo> packages = pm.getInstalledPackages(0);
        ArrayList<RunningAppProcessInfoWrap> tempList = new ArrayList<RunningAppProcessInfoWrap>();
        
        Iterator<PackageInfo> appInfoIterator = packages.iterator();
        while (appInfoIterator.hasNext()) {
            PackageInfo pi = (PackageInfo) appInfoIterator.next();
            ApplicationInfo ai = pi.applicationInfo;
            if (!isSystemApplications(ai)) {
                String packageName = pi.packageName;
                RunningAppProcessInfoWrap apkInfo = checkAutoAppStatus(context, packageName);
                if (apkInfo.mBootFlag != 0) {
                    apkInfo.setDispName(pm.getApplicationLabel(ai).toString());
                    if (rootPermission) if (apkInfo.mEnable) apkList.add(apkInfo);
                    tempList.add(apkInfo);
                }
            }
        }
//        Collections.sort(tempList, new ApkComparator());
        return tempList;
    }
    
    
    /**
     *判断应用自启动状态 默认为false 0:没有自启动能力 1:开机自启 2:后台自启 3:开机自启和后台自启
     * @param context
     * @param packageName
     * @return
     */
    public int checkAutoAppStatusByCode(Context context, String packageName) {
        PackageManager pm = context.getPackageManager();
        int status = 0;
        Intent intent = new Intent();
        intent.setPackage(packageName);
        intent.setAction(BOOT_COMPLEMENT_ACTION);
        String args[] = new String[2];
        List<ResolveInfo> list = pm.queryBroadcastReceivers(intent, 512);
        if (list != null && list.size() > 0) {
            Iterator<ResolveInfo> rifInterator = list.iterator();
            while (rifInterator.hasNext()) {
                ResolveInfo rif = (ResolveInfo) rifInterator.next();
                args[0] = packageName;
                args[1] = rif.activityInfo.name;
                String component = String.format("%s/%s", args);
                ComponentName cn = ComponentName.unflattenFromString(component);
                if (pm.getComponentEnabledSetting(cn) == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
//                    autoApp.mEnable = false;
                }
                status++;
                break;
            }
        }

        int length = BACKGROUND_BOOT_RECEIVER.length;
        for (int i = 0; i < length; i++) {
            intent.setPackage(packageName);
            intent.setAction(BACKGROUND_BOOT_RECEIVER[i]);
            List<ResolveInfo> rifList = pm.queryBroadcastReceivers(intent, 512);
            if (rifList != null && rifList.size() > 0) {
                Iterator<ResolveInfo> rifInterator = rifList.iterator();
                while (rifInterator.hasNext()) {
                    ResolveInfo rif = (ResolveInfo) rifInterator.next();
                    args[0] = packageName;
                    args[1] = rif.activityInfo.name;
                    String component = String.format("%s/%s", args);
                    ComponentName cn = ComponentName.unflattenFromString(component);
                    if (pm.getComponentEnabledSetting(cn) == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
//                        autoApp.mEnable = false;
                    }
                    if (status == 1)
                        status = 3;
                    else {
                        status = 2;
                    }
                }
            }
        }
        return status;
    }
    
    
    //判断应用自启动状态 默认为false 0:没有自启动能力 1:开机自启 2:后台自启 3:开机自启和后台自启
    public RunningAppProcessInfoWrap checkAutoAppStatus(Context context, String packageName) {
        PackageManager pm = context.getPackageManager();
        int status = 0;
        Intent intent = new Intent();
        intent.setPackage(packageName);
        intent.setAction(BOOT_COMPLEMENT_ACTION);
        
        RunningAppProcessInfoWrap autoApp = new RunningAppProcessInfoWrap(packageName);
        
        String args[] = new String[2];
        List<ResolveInfo> list = pm.queryBroadcastReceivers(intent, 512);
        if (list != null && list.size() > 0) {
            Iterator<ResolveInfo> rifInterator = list.iterator();
            while (rifInterator.hasNext()) {
                ResolveInfo rif = (ResolveInfo) rifInterator.next();
                args[0] = packageName;
                args[1] = rif.activityInfo.name;
                String component = String.format("%s/%s", args);//com.fan.music/com.fan.music.MyReceiver
                autoApp.add(component);
                ComponentName cn = ComponentName.unflattenFromString(component);//ComponentInfo{com.fan.music/com.fan.music.MyReceiver}
                if (pm.getComponentEnabledSetting(cn) == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
                    autoApp.mEnable = false;
                }
                status++;
                break;
            }
        }

        int length = BACKGROUND_BOOT_RECEIVER.length;
        for (int i = 0; i < length; i++) {
            intent.setPackage(packageName);
            intent.setAction(BACKGROUND_BOOT_RECEIVER[i]);
            List<ResolveInfo> rifList = pm.queryBroadcastReceivers(intent, 512);
            if (rifList != null && rifList.size() > 0) {
                Iterator<ResolveInfo> rifInterator = rifList.iterator();
                while (rifInterator.hasNext()) {
                    ResolveInfo rif = (ResolveInfo) rifInterator.next();
                    args[0] = packageName;
                    args[1] = rif.activityInfo.name;
                    String component = String.format("%s/%s", args);
                    autoApp.add(component);
                    ComponentName cn = ComponentName.unflattenFromString(component);
                    if (pm.getComponentEnabledSetting(cn) == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
                        autoApp.mEnable = false;
                    }
                    if (status == 1)
                        status = 3;
                    else {
                        status = 2;
                    }
                }
            }
        }
        autoApp.mBootFlag = status;
        return autoApp;
    }
    
    /**
     * 允许应用自动启动
     * @param context
     * @param packageName
     */
    public void enableAutoLaunch(Context context, String packageName,IRemoteExecute execute) {
        PackageManager pm = context.getPackageManager();
        Intent intent = new Intent();
        intent.setPackage(packageName);
        intent.setAction(BOOT_COMPLEMENT_ACTION);
        String args[] = new String[2];
        List<ResolveInfo> list = pm.queryBroadcastReceivers(intent, 512);
        if (list != null && list.size() > 0) {
            Iterator<ResolveInfo> rifInterator = list.iterator();
            while (rifInterator.hasNext()) {
                ResolveInfo rif = (ResolveInfo) rifInterator.next();
                args[0] = packageName;
                args[1] = rif.activityInfo.name;
                String component = String.format("%s/%s", args);
                if (component.contains("$")) {
                    component = component.replace("$", "\\$");
                }
                String cmd = String.format("pm enable %s\n", component);
                executeCmd(execute, cmd);
            }
        }

        int length = BACKGROUND_BOOT_RECEIVER.length;

        for (int i = 0; i < length; i++) {
            intent.setPackage(packageName);
            intent.setAction(BACKGROUND_BOOT_RECEIVER[i]);
            List<ResolveInfo> rifList = pm.queryBroadcastReceivers(intent, 512);
            if (rifList != null && rifList.size() > 0) {
                Iterator<ResolveInfo> rifInterator = rifList.iterator();
                while (rifInterator.hasNext()) {
                    ResolveInfo rif = (ResolveInfo) rifInterator.next();
                    args[0] = packageName;
                    args[1] = rif.activityInfo.name;
                    String component = String.format("%s/%s", args);
                    if (component.contains("$")) {
                        component = component.replace("$", "\\$");
                    }
                    String cmd = String.format("pm enable %s\n", component);
                    executeCmd(execute, cmd);
                }
            }
        }
    }

    
    /**
     * 禁止应用自动启动
     * 
     * @param context
     * @param packageName
     */
    public void disableAutoLaunch(Context context, String packageName , IRemoteExecute execute) {
        PackageManager pm = context.getPackageManager();
        Intent intent = new Intent();
        intent.setPackage(packageName);
        intent.setAction(BOOT_COMPLEMENT_ACTION);
        String args[] = new String[2];

        List<ResolveInfo> list = pm.queryBroadcastReceivers(intent, 512);

        if (list != null && list.size() > 0) {
            Iterator<ResolveInfo> rifInterator = list.iterator();
            while (rifInterator.hasNext()) {
                ResolveInfo rif = (ResolveInfo) rifInterator.next();
                args[0] = packageName;
                args[1] = rif.activityInfo.name;
                String component = String.format("%s/%s", args);
                if (component.contains("$")) {
                    component = component.replace("$", "\\$");
                }

                String cmd = String.format("pm disable %s\n", component);
                System.out.println("cmd is " + cmd);
                
                executeCmd(execute, cmd);
            }
        }
        int length = BACKGROUND_BOOT_RECEIVER.length;
        for (int i = 0; i < length; i++) {
            intent.setPackage(packageName);
            intent.setAction(BACKGROUND_BOOT_RECEIVER[i]);
            List<ResolveInfo> rifList = pm.queryBroadcastReceivers(intent, 512);
            if (rifList != null && rifList.size() > 0) {
                Iterator<ResolveInfo> rifInterator = rifList.iterator();
                while (rifInterator.hasNext()) {
                    ResolveInfo rif = (ResolveInfo) rifInterator.next();
                    args[0] = packageName;
                    args[1] = rif.activityInfo.name;
                    String component = String.format("%s/%s", args);
                    if (component.contains("$")) {
                        component = component.replace("$", "\\$");
                    }

                    String cmd = String.format("pm disable %s\n", component);
                    executeCmd(execute, cmd);
                }
            }
        }
    }

	private void executeCmd(IRemoteExecute execute, String cmd) {
		
		try {
//			RootUtilSingleton.getInstance().writeCmd(cmd, 100);
			System.out.println("================== " + android.os.Process.myUid() + "  " + Process.SYSTEM_UID);
			if(android.os.Process.myUid() == Process.SYSTEM_UID){
				JavaShellUtil shell = new JavaShellUtil();
				shell.executeLocalCmd(cmd);
			}else{
				if(execute != null){
					execute.execute(null, cmd);
				}
			}
            
		} catch (Exception e) {
		    e.printStackTrace();
		}
	}
	
	
	public void getCurrentTask(){
		IActivityManager im = ActivityManagerNative.getDefault();
		try {
			@SuppressWarnings("unchecked")
			List<RunningTaskInfo> tasks = im.getTasks(9, 0, null);
			for (RunningTaskInfo runningTaskInfo : tasks) {
				System.out.println(runningTaskInfo.baseActivity.getPackageName());
			}
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取应用的图标
	 */
	public Drawable getAppIcon(String packname){
		try {
			ApplicationInfo info = mPkgManager.getApplicationInfo(packname, 0);
			return info.loadIcon(mPkgManager);
		} catch (NameNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
}
